import 'dart:convert';

import 'package:sl_doclever/src/doclever/sl_doc_config.dart';
import 'package:sl_doclever/src/doclever/sl_doc_data.dart';
import 'package:sl_doclever/src/doclever/sl_node.dart';
import 'package:sl_doclever/src/objc/sl_objc_code.dart';
import 'package:sl_doclever/src/objc/sl_objc_out.dart';
import 'package:core_extension/core_extension.dart';

class SLObjc {
  List<SLObjcOut> outObjc;
  Map outFiles;

  final SLDocData docData;

  SLObjc(this.docData) {
    outObjc = toObjcModel();
    outFiles = toModelFiles();
  }

  List<SLObjcOut> toObjcModel() {
    var out = <SLObjcOut>[];

    try {
      for (var fNode in docData.allNodesName(docData.outParam)) {
        var outH = [];
        var outM = [];
        var arrayClses = [];

        var clsName = fNode.codeType + SLDocConfig().daoEnd.sl_capitalize();

        outH.add(SLObjcCode.interface(
          clsName,
          docData.name,
        ));

        outM.add(SLObjcCode.implementation(clsName));

        // 变量
        var impl_var_init = [];
        docData.outParam.forEach((node) {
          if (fNode.faterNode == node.faterNode) {
            var data_type = '';

            /// 获取到类型中的自定义类名
            if (node.type == SLNodeType.Object ||
                node.type == SLNodeType.Array) {
              for (var i in docData.allNodesName(docData.outParam)) {
                if (node.name == i.faterNode) {
                  data_type = i.codeType + SLDocConfig().daoEnd.sl_capitalize();
                  break;
                }
              }
            }

            if (node.type == SLNodeType.String) {
              outH.add(SLObjcCode.property_NSString(
                node.name,
                node.remark,
              ));

              impl_var_init.add(SLObjcCode.property_NSString_init(node.name));
            } else if (node.type == SLNodeType.Object) {
              outH.add(SLObjcCode.property_NSObject(
                data_type,
                node.name,
                node.remark,
              ));

              impl_var_init.add(SLObjcCode.property_NSObject_init(
                data_type,
                node.name,
              ));
            } else if (node.type == SLNodeType.Array) {
              arrayClses.add('@"${node.name}" : [$data_type class]');

              outH.add(SLObjcCode.property_NSArray(
                data_type,
                node.name,
                node.remark,
                hasSub: docData.hasSubNodes(docData.outParam, node.name),
              ));

              impl_var_init.add(SLObjcCode.property_NSArray_init(
                data_type,
                node.name,
              ));
            }
          }
        });

        outH.add(SLObjcCode.end());

        out.add(SLObjcOut(
          format: 'h',
          codeString: outH.join('\n'),
          node: fNode.faterNode,
          isRoot: fNode.faterNode == SLDocConfig().root ? true : false,
          fileName: clsName,
        ));

        if (impl_var_init.isNotEmpty) {
          outM.add(SLObjcCode.init(impl_var_init));
        }
        if (arrayClses.isNotEmpty) {
          outM.add(SLObjcCode.modelContainerPropertyGenericClass(arrayClses));
        }

        outM.add(SLObjcCode.end());

        out.add(SLObjcOut(
          format: 'm',
          codeString: outM.join('\n'),
          node: fNode.faterNode,
          isRoot: fNode.faterNode == SLDocConfig().root ? true : false,
          fileName: clsName,
        ));
      }
    } catch (e, s) {
      print('$e,$s');
    }
    return out;
  }

  Map toModelFiles() {
    var ret = {};
    if (outObjc == null || outObjc.isEmpty) return ret;

    var outHList = [];
    var outHList_Class = [];
    var outHName = '';

    var outMList = [];
    var outMList_Class = [];
    var outMName = '';

    outObjc.forEach((el) {
      if (el.format == 'h') {
        outHList_Class.add('@class ${el.fileName};');
        outHList.add(el.codeString);
        if (el.isRoot) outHName = '${el.fileName}.${el.format}';
      }

      if (el.format == 'm') {
        outMList_Class.add('@class ${el.fileName};');
        outMList.add(el.codeString);
        if (el.isRoot) outMName = '${el.fileName}.${el.format}';
      }
    });

    outHList.insert(0, outHList_Class.join('\n'));
    outHList.insert(0, '/*\n${json.encode(docData.outParamJson)}\n*/');
    outHList.insert(0, SLObjcCode.interface_sys());

    outMList.insert(0, SLObjcCode.implementation_import(outHName));

    if (outHName.isNotEmpty) ret[outHName] = outHList.join('\n\n');
    if (outMName.isNotEmpty) ret[outMName] = outMList.join('\n\n');

    return ret;
  }
}
